package chpt09;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

class CalcTask implements Runnable {
	private int n;

	public CalcTask(int n) {
		this.n = n;
	}

	@Override
	public void run() {
		int sum = 0;
		for (int i = 1; i < n + 1; i++) {
			sum += i;
		}
		String name = Thread.currentThread().getName();
		System.out.printf("%s: n = %d, sum = %d%n", name, n, sum);
	}

}

class CalCallableTask implements Callable<Integer>{
	private int n;
	
	public CalCallableTask(int n) {
		this.n = n;
	}

	@Override
	public Integer call() throws Exception {
		Random rnd = new Random();
		int sum = 0;
		for (int i = 1; i < n + 1; i++) {
			sum += i;
		}
		int sleeTime = rnd.nextInt(10);
		TimeUnit.SECONDS.sleep(sleeTime);
		String name = Thread.currentThread().getName();
		System.out.printf("%s 计算的结果为 %d! 共花费 %d 秒时间%n",name,sum, sleeTime);
		return sum;
	}
	
}

public class ExecutorServiceTest {

	public static void main(String[] args)  {
		//testRunnable();
		//testCallable();
		//testInvoke();
		testExecutorCompletion();
		
	}


	private static void testRunnable() {
		ExecutorService pool = Executors.newSingleThreadExecutor();
		//ExecutorService executor = Executors.newCachedThreadPool();
		/*int processorsNums = Runtime.getRuntime().availableProcessors();
		System.out.println("当前计算机有"+processorsNums+"个内核");
		ExecutorService executor = Executors.newFixedThreadPool(processorsNums);*/
		int begin = 10, end = 15;
		// 创建end-begin个任务交给executor执行
		for (int i = begin; i < end; i++) {
			pool.execute(new CalcTask(i));
		}
		pool.shutdown();
	}
	
	private static void testCallable() {
		ExecutorService pool = Executors.newCachedThreadPool();
		int begin = 10, end = 15;
		List<Future<Integer>> results = new ArrayList<>();
		for (int i = begin; i < end; i++) {
			results.add(pool.submit(new CalCallableTask(i)));
		}
		System.out.println("---计算结果---");
		for (Future<Integer> e : results) {
			try {
				System.out.println(e.get());
			} catch (InterruptedException | ExecutionException e1) {
				e1.printStackTrace();
			}
		}
		pool.shutdown();
		
	}
	
	private static void testInvoke()  {
		ExecutorService pool = Executors.newCachedThreadPool();
		int begin = 10, end = 15;
		List<Callable<Integer>> tasks = new ArrayList<>();  //任务列表
		for (int i = begin; i < end; i++) {
			tasks.add(new CalcCallableTask(i));
		}
		//invokeAll 
		/*try {
			results = pool.invokeAll(tasks);
		} catch (Exception e) {
			e.printStackTrace();
		} 
		System.out.println("---计算结果---");
		for (Future<Integer> e : results) {
			try {
				System.out.println(e.get());
			} catch (InterruptedException | ExecutionException e1) {
				e1.printStackTrace();
			}
		}*/
		
		//invokeAny 
		Integer x;
		try {
			x = pool.invokeAny(tasks);
			//x = pool.invokeAny(tasks, 1, TimeUnit.SECONDS);
			System.out.println("其中一个线程计算的结果为: "+x);
		} catch (InterruptedException | ExecutionException e) {
			e.printStackTrace();
		} 
		
		pool.shutdownNow();
		
	}
	

	private static void testExecutorCompletion() {
		ExecutorService pool = Executors.newCachedThreadPool();
		int begin = 10, end = 15;
		List<Callable<Integer>> tasks = new ArrayList<>();  //任务列表
		for (int i = begin; i < end; i++) {
			tasks.add(new CalcCallableTask(i));
		}
		ExecutorCompletionService<Integer> service = 
				new ExecutorCompletionService<>(pool);
		
		for (Callable<Integer> e : tasks) {
			service.submit(e);
		}
		
		System.out.println("---计算结果---");
		for (int i = 0; i < tasks.size(); i++) {
			try {
				System.out.println(service.take().get());
			} catch (InterruptedException | ExecutionException e1) {
				e1.printStackTrace();
			}
		}
		
		pool.shutdown();
	}

}
